﻿/*
* Copyright (c) 2010, Omer
* All rights reserved.
* The code is under the BSD license.
* http://minecraftbackup.codeplex.com/license
*/

using System;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Microsoft.Win32;

namespace MinecraftBackupAssistant
{
    static class Program
    {
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool AllocConsole();

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool FreeConsole();

        [DllImport("kernel32", SetLastError = true)]
        static extern bool AttachConsole(int dwProcessId);

        [DllImport("user32.dll")]
        static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll", SetLastError = true)]
        static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);

		

		private static void helpScreen()
		{
			Console.WriteLine("\n\nMinecraft Backup Assistant by omer681, version {0}\n", Application.ProductVersion);
			Console.WriteLine("Usage: mba WORLDFOLDER OUTPUTFOLDER [-zip]");
		}

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
			string savesFolder = Utility.CombinePath(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), ".minecraft", "saves");
			bool success = true;

            if (args.Length > 0)
            {
                //Get a pointer to the forground window.  The idea here is that
                //IF the user is starting our application from an existing console
                //shell, that shell will be the uppermost window.  We'll get it
                //and attach to it
                IntPtr ptr = GetForegroundWindow();
                int u;
                GetWindowThreadProcessId(ptr, out u);
                System.Diagnostics.Process process = System.Diagnostics.Process.GetProcessById(u);

                if (process.ProcessName == "cmd")    //Is the uppermost window a cmd process?
                {
                    AttachConsole(process.Id);
                }
                else
                {
                    AllocConsole();
                }

				if (args[0] == "-help")
				{
					helpScreen();
					exitProgram(0);
				}

				Console.WriteLine("\n");

                string worldPath = args[0];
                if (!Directory.Exists(worldPath))
                {
                    Console.WriteLine("nThe world folder does not exist. Type mba -help to show the help screen.");
                    exitProgram(1);
                }

                string backupPath = args[1];
                if (!Directory.Exists(backupPath))
                {
					Console.WriteLine("The output folder does not exist. Type mba -help to show the help screen.");
					exitProgram(1);
                }

                bool shouldZip = false;
				if (args.Length == 3 && args[2] == "-zip")
					shouldZip = true;
				else if (args.Length == 2)
					shouldZip = false;
				else
				{
					Console.WriteLine("Wrong syntax. Type mba -help to show the help screen. ");
					exitProgram(1);
				}

                Action<Exception> onCriticalError = new Action<Exception>((e) => 
                    {
                        Console.Write("Error: {0}\nYou can report any error at http://minecraftbackup.codeplex.com/discussions \nPress y to get more information about the error, or any other key to continue", e.Message);
                        char c = Console.ReadKey(true).KeyChar;
                        if (c == 'y')
                        {
                            success = false;
                            Console.WriteLine("\n================================================================================");
                            Console.WriteLine("Message: {0}\n\nStack Trace:\n{1}",e.Message, e.StackTrace);
                            if (e.InnerException != null)
                                Console.Write("\n\n\tInner Exception:\n\n\tMessage: {0}\n\n\tStack Trace: {1}", e.Message, e.StackTrace);
                        }
                    });

                Action<Exception> onMinorError = new Action<Exception>((e) => Console.WriteLine("Error: " + e.Message));
                Action<string> messageOutput = new Action<string>((str) =>
                    {
                        Console.BackgroundColor = ConsoleColor.Black;
						Console.SetCursorPosition(0, 0);
                        Console.Write("                                                  ");
                        Console.SetCursorPosition(0, 0);
                        Console.Write(str);
                    });
                Action<int, int> updateProgress = new Action<int, int>((max, value) =>
                    {
                        if (value % 5 == 0)
                        {
                            Console.SetCursorPosition(50, 0);
                            int length = 20;
                            int val = (int)((double)value / (double)max * 20);
                            Console.Write("[");
                            for (int i = 0; i < val; i++)
                            {
                                Console.BackgroundColor = ConsoleColor.White;
                                Console.Write(" ");
                            }
                            for (int i = val; i < length - 1; i++)
                            {
                                Console.BackgroundColor = ConsoleColor.Black;
                                Console.Write(" ");
                            }
                            Console.BackgroundColor = ConsoleColor.Black;
                            Console.Write("]");
                        }
                    });
                Backup backup = new Backup(new BackupInformation(shouldZip, worldPath, false, backupPath, new DirectoryInfo(worldPath).Name, "", null, "", null, 0), null, null, null, onCriticalError, onMinorError, Console.WriteLine, false);
                backup.BackupWorld();
                Console.BackgroundColor = ConsoleColor.Black;
                if (success)
                    Console.WriteLine((shouldZip ? "\nZIP backup" : "\nBackup") + " to {0} has been saved at {1}.", new DirectoryInfo(worldPath).Name, backupPath);
            
				exitProgram(success ? 0 : 1);
			}



            using (Mutex mutex = new Mutex(false, "MBAMutex")) //to avoid running the program twice
            {
                if (mutex.WaitOne(0, false))
                {
                    try
                    {
                        Utility.PrepareDirectories();
                        if (Properties.Settings.Default.BackupPath == "") Properties.Settings.Default.SettingsEdited = false;
                        if (Properties.Settings.Default.MapperSettings == null) Properties.Settings.Default.MapperSettings = new MapperSettings();
                        Application.EnableVisualStyles();
                        Application.SetCompatibleTextRenderingDefault(false);
                        if (Properties.Settings.Default.CheckForUpdates)
                        {
                            Thread updateThread = new Thread(() =>
                                {
                                    try
                                    {
                                        if (UpdateChecker.Update(false) == false) //if the user pressed no...
                                            if (MessageBox.Show("Do you want to disable automatic update checks?", "Automatic Updates Checks", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                                            {
                                                Properties.Settings.Default.CheckForUpdates = false;
                                                Properties.Settings.Default.Save();
                                            }
                                    }
                                    catch
                                    {
                                    }
                                });
                            updateThread.Start();
                        }

                        if (Properties.Settings.Default.FirstTimeLaunched)
                        {
                            string path = Utility.CombinePath(new FileInfo(Assembly.GetExecutingAssembly().Location).DirectoryName, "Readme.txt");
                            if (File.Exists(path))
                                Process.Start(path);
                            Properties.Settings.Default.FirstTimeLaunched = false;
                        }
                        //Utility.HandleError(new Exception());
                        MainForm form = new MainForm();
                        form.Icon = System.Drawing.Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);
                        Application.Run(form);
                        if (Directory.Exists(Utility.CombinePath(Path.GetTempPath(), "MinecraftBackupAssistant"))) Utility.DeleteDirectory(Utility.CombinePath(Path.GetTempPath(), "MinecraftBackupAssistant"));
                    }
                    catch (Exception e)
                    {
                        MessageBox.Show(e.Message + "\n\n\n" + e.StackTrace);
                    }
                }
                else
                    MessageBox.Show("The program is already running!", "The program is already running", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private static void exitProgram(int exitCode)
        {
            //Console.WriteLine("\nPress any key to continue.");
            //Console.ReadKey(true);
            //FreeConsole();
            Environment.Exit(exitCode);
        }
    }
}